home *** CD-ROM | disk | FTP | other *** search
/ MacWorld Secrets (4th Edition) / Mac Secrets CD 4th Ed.toast / Apple Advanced Technologies / Apple Speech Technologies 1.5 / PlainTalk Developer Info / Speech Recognition Manager SDK / SR Sample Code / Speakable Items Example / Sources / Main.c next >
Text File  |  1996-03-18  |  19KB  |  678 lines

  1. /*****************************************************************************/
  2.  
  3.  
  4. #include "SpeechRecognition.h"
  5. #include "GestaltEqu.h"
  6. #include "Quickdraw.h"
  7. #include "Dialogs.h"
  8. #include "Fonts.h"
  9. #include "AppleEvents.h"
  10. #include "string.h"
  11. #include "Speech.h"
  12. #include <Packages.h>
  13.  
  14. #include "SpeakableItems.h"
  15.  
  16. // Comment following out, and set SIZE background-only bit to make faceless version
  17. #define __HAS_UI__
  18.  
  19. //#define __USE_CALLBACKS__
  20.  
  21. /*****************************************************************************/
  22.  
  23. /* Prototypes and globals */
  24.  
  25. OSErr    InitStuff (void);
  26. OSErr    InitAndStartSpeechRecognition (void);
  27. void    MainLoop (void);
  28. void    SayDateOrTime (Boolean date);
  29. #ifdef __HAS_UI__
  30. void    HandleMouseDown (EventRecord *theEvent);
  31. void     HandleUpdate (EventRecord *theEvent);
  32. void    HandleMenuSelect (long menuChoice);
  33. #endif
  34. void    CleanupStuff (void);
  35. void    CleanupSpeechRecognitionStuff (void);
  36. OSErr    MakeALanguageModel (SRLanguageModel *lm);
  37. pascal OSErr HandleQuitAE (AppleEvent *theAEevt, AppleEvent* reply, long refcon);
  38. pascal OSErr DummyAEHandler (AppleEvent *theAEevt, AppleEvent* reply, long refcon);
  39. void    ProcessResult (OSErr origStatus, SRRecognitionResult recResult);
  40. #ifdef __USE_CALLBACKS__
  41. pascal void MyNotificationCallBack (SRCallBackStruct *param);
  42. #else
  43. pascal    OSErr HandleSpeechDoneAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon);
  44. pascal    OSErr HandleSpeechBeginningAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon);
  45. #endif
  46.  
  47. #ifdef __HAS_UI__
  48. void    DisplayString (Str255 str);
  49. #endif
  50.  
  51. #ifdef __HAS_UI__
  52. #define    kAppleMenu    1
  53. #define    kFileMenu    2
  54. #define kFirstMenu    kAppleMenu
  55. #define kLastMenu    kFileMenu
  56.  
  57. DialogPtr             gDialog;
  58. MenuHandle            gMenuHandles[kLastMenu];
  59. #endif
  60.  
  61. SRRecognitionSystem    gSystem = 0;
  62. SRRecognizer            gRecognizer = 0;
  63. SRLanguageModel        gTopLM = 0;
  64. SRLanguageModel        gSIModel = 0;            /* For SpeakableItems */
  65. Boolean                gFinished;
  66. Str255                gLastStr;
  67. SRCallBackStruct     gCallBackInfo;
  68.  
  69. #define    kTopLMRefCon        10000
  70. #define kQuitSpeakableItems    10002
  71. #define kWhatTimeIsIt        10004
  72. #define kWhatDayIsIt        10006
  73.  
  74. #define kSimpleStrsID         500
  75. #define kQuitStr            1
  76. #define kWhatTimeIsItStr    2
  77. #define kWhatDayIsItStr        3
  78.  
  79. /*****************************************************************************/
  80.  
  81. void main (void)
  82. {
  83.     OSErr    status = InitStuff ();
  84.     if (!status) {
  85.         MainLoop ();
  86.         CleanupStuff ();
  87.     }
  88. }
  89.  
  90. /*****************************************************************************/
  91.  
  92. /* main is the entry point to his program.    */
  93.  
  94. OSErr InitStuff (void)
  95. {
  96.     OSErr                status = noErr;
  97.     Rect                rBounds;
  98.     GrafPtr                oldPort;
  99.     SRLanguageObjectFlags                autoFin = kSRNoFinishing;
  100.     MenuHandle            menuH;
  101.     short                i;
  102.     
  103.         /* Adjust heap */
  104. #ifdef __HAS_UI__
  105.     MaxApplZone();
  106.     MoreMasters();
  107.     MoreMasters();
  108. #endif
  109.     
  110.         /* Init toolboxes */
  111.     InitGraf(&qd.thePort);
  112. #ifdef __HAS_UI__
  113.     InitFonts();
  114.     FlushEvents(everyEvent,0);
  115.     InitWindows();
  116.     InitMenus();
  117.     TEInit();
  118.     InitDialogs(0);
  119.     InitCursor();
  120. #endif
  121.  
  122. #ifdef __HAS_UI__
  123.     for (i = kFirstMenu; i <= kLastMenu; i++) {
  124.         menuH = GetMenu(i);
  125.         gMenuHandles[i-1] = menuH;
  126.         if (menuH) InsertMenu (menuH, 0);
  127.     }
  128.     menuH = gMenuHandles[kAppleMenu-1];
  129.     if (menuH) AddResMenu(menuH,'DRVR');
  130.     DrawMenuBar();
  131.  
  132.  
  133.         /* Make a dialog in which we'll display results */
  134.     SetRect (&rBounds, 50,50,450,150);
  135.     gDialog = NewDialog(NULL,&rBounds,"\p",true,noGrowDocProc,(WindowPtr)-1,true,0,NULL);
  136.     if (!gDialog)
  137.         status = -1;
  138. #endif    
  139.     
  140.     if (!status)
  141.         status = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, 
  142.                                 NewAEEventHandlerProc (DummyAEHandler), 0, false);
  143.     if (!status)
  144.         status = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 
  145.                                 NewAEEventHandlerProc (DummyAEHandler), 0, false);
  146.     if (!status)
  147.         status = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, 
  148.                                 NewAEEventHandlerProc (DummyAEHandler), 0, false);
  149.     if (!status)
  150.         status = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, 
  151.                                 NewAEEventHandlerProc (HandleQuitAE), 0, false);
  152.  
  153.     if (!status)
  154.         status = InitAndStartSpeechRecognition ();
  155.     
  156.     
  157.     if (!status)
  158.         gFinished = false;
  159.     else
  160.         gFinished = true;
  161.  
  162. }
  163.  
  164. /*****************************************************************************/
  165.  
  166. /* This routine initializes speech recognition, installs an AppleEvent handler
  167.     to handle result notifications from the Speech Recognition Toolbox, calls
  168.     another routine to build a simple language model (which specifies a few
  169.     phrases a user can say), makes that language model active by calling
  170.     SRSetLanguageModel, and starts the recognizer listening.  A more realistic
  171.     application would have more complicated language models (perhaps having
  172.     different language models for different contexts -- using SRSetLanguageModel
  173.     to make the appropriate one active), or would use the language model
  174.     manipulation routines in the Speech Recognition Toolbox to change the
  175.     active language model as the program was used to reflect what the user
  176.     might say in any given situation.
  177. */
  178.  
  179. OSErr InitAndStartSpeechRecognition ()
  180. {
  181.     OSErr            status;
  182.     long            attributes;
  183.     Boolean         fgOnly = false;
  184.     SRCallBackParam    callBackPB;
  185.     long            notifFlags = kSRNotifyRecognitionBeginning | kSRNotifyRecognitionDone;
  186.     
  187. #ifdef __HAS_UI__
  188.     /* The SROpenRecognitionSystem loads lots of data and takes a few
  189.         seconds, so display a message indicating this will take a moment.
  190.         This would be a good place to show the watch cursor as well. */
  191.     DisplayString ("\pStarting up...");
  192. #endif
  193.         /* Make sure SpeechRecognition Toolbox is available */
  194.     status = Gestalt (gestaltSpeechRecognitionVersion, &attributes);
  195.     
  196.         /* Open a SRRecognitionSystem */
  197.     if (!status)
  198.         status = SROpenRecognitionSystem (&gSystem, kSRDefaultRecognitionSystemID);
  199.  
  200.         /* Create a recognizer with default speech source -- e.g. the desktop microphone */
  201.     if (!status)
  202.         status = SRNewRecognizer (gSystem, &gRecognizer, kSRDefaultSpeechSource);
  203.                 
  204.     if (!status)
  205.         status = SRSetProperty (gRecognizer, kSRForegroundOnly, &fgOnly, sizeof(fgOnly));
  206.     if (!status)
  207.         status = SRSetProperty (gRecognizer, kSRNotificationParam, ¬ifFlags, sizeof(notifFlags));
  208.         
  209. #ifdef __USE_CALLBACKS__
  210.         /* Install call-back */
  211.     if (!status) {
  212.         callBackPB.callBack = NewSRCallBackProc (MyNotificationCallBack);
  213.         callBackPB.param = &gCallBackInfo;
  214.         status = SRSetProperty (gRecognizer, kSRCallBackParam, &callBackPB, sizeof (callBackPB));
  215.     }
  216. #else
  217.         /* Install an AppleEvent handler so recognizer can send us recognition results. */
  218.     if (!status)
  219.         status = AEInstallEventHandler(kAESpeechSuite, kAESpeechDone, 
  220.                                     NewAEEventHandlerProc (HandleSpeechDoneAppleEvent), 0, false);
  221.     if (!status)
  222.         status = AEInstallEventHandler(kAESpeechSuite, kAESpeechDetected, 
  223.                                     NewAEEventHandlerProc (HandleSpeechBeginningAppleEvent), 0, false);
  224. #endif
  225.                             
  226.         /* For this example, we will just make one language model,
  227.             make it active, and start listening. */
  228.  
  229.         /* Make a simple language model (LM) */
  230.     if (!status)
  231.         status = MakeALanguageModel (&gTopLM);
  232.  
  233.         /* Use this LM in recognition */
  234.     if (!status)
  235.         status = SRSetLanguageModel (gRecognizer, gTopLM);
  236.  
  237.         /* Have the recognizer start processing sound */
  238.     if (!status)
  239.         status = SRStartListening (gRecognizer);
  240.  
  241.         /* Initialize Speakable Items unit and get an LM representing
  242.             the speakable items, and add it to our top level LM. */
  243.             
  244.     if (!status)
  245.         status = SIInitSpeakableItems (gSystem, &gSIModel);
  246.  
  247.     if (!status && gSIModel)
  248.         status = SRAddLanguageObject (gTopLM, gSIModel);
  249.  
  250. #ifdef __HAS_UI__
  251.     if (!status)
  252.         DisplayString ("\pReady");
  253.     else
  254.         // Couldn't run for some reason.  Perhaps there is no 'Speakable Items' folder in the 'Apple Menu Items' folder,
  255.         //    or perhaps Speech Recognition extension is not installed.
  256.         DisplayString ("\pSorry, Can't run. See trouble shooting notes.");
  257. #endif
  258.  
  259.     return status;
  260. }
  261.  
  262.  
  263. /*****************************************************************************/
  264.  
  265. void MainLoop ()
  266. {
  267.     Boolean         gotEvent;
  268.     EventRecord        event;
  269.     DialogPtr        theDialog;
  270.     short            itemHit;
  271.     long            sleepTime;
  272.     char            ch;
  273.     
  274.         /* Here's our overly-simple main event loop */
  275.         /*    We quit if mouse is clicked in window,    */
  276.         /*    or if any key is clicked.                */
  277.         /*    We also dispatch AppleEvents.            */
  278.     while (!gFinished) {
  279.         if (gFinished) sleepTime = 1; else sleepTime = 0xFFFFFFFF;
  280.         gotEvent = WaitNextEvent(everyEvent, &event, sleepTime, NULL);
  281.         if (gotEvent) {
  282.             switch (event.what) {
  283. #ifdef __HAS_UI__
  284.                 case mouseDown :
  285.                     HandleMouseDown (&event);
  286.                     break;
  287.                 case keyDown :
  288.                     ch = event.message & charCodeMask;
  289.                     if (event.modifiers & cmdKey)
  290.                         HandleMenuSelect (MenuKey(ch));
  291.                     break;
  292.                 case updateEvt :
  293.                     HandleUpdate (&event);
  294.                     break;
  295. #endif
  296.                 case kHighLevelEvent :
  297.                     AEProcessAppleEvent(&event);
  298.                     break;
  299.                 default :
  300.                     break;
  301.             }
  302.         }
  303. #ifdef __HAS_UI__
  304.         if (IsDialogEvent(&event))
  305.             DialogSelect(&event, &theDialog, &itemHit);
  306. #endif
  307.         if (!gFinished)
  308.             SIUpdateSpeakableItems (gSystem, gSIModel);
  309.     }
  310. }
  311.  
  312. /*****************************************************************************/
  313.  
  314. #ifdef __HAS_UI__
  315. void HandleMouseDown (EventRecord *theEvent)
  316. {
  317.     WindowPtr    theWindow;
  318.     short        inWhatPart = FindWindow (theEvent->where, &theWindow);
  319.     Point        pt = theEvent->where;
  320.     GrafPtr        oldPort;
  321.     Rect        rct;
  322.     
  323.     switch (inWhatPart) {
  324.         case inSysWindow :
  325.             SystemClick (theEvent, theWindow);
  326.             break;
  327.         case inContent:
  328.             break;
  329.         case inMenuBar :
  330.             HandleMenuSelect (MenuSelect(theEvent->where));
  331.             break;
  332.         case inDrag :
  333.             rct = qd.screenBits.bounds;
  334.             InsetRect (&rct, 20, 20);
  335.             DragWindow (theWindow, pt, &rct);
  336.             break;
  337.         case inGoAway:
  338.             if (TrackGoAway (theWindow, pt))
  339.                 gFinished = true;
  340.             break;
  341.         default :
  342.             break;
  343.     }
  344.     HiliteMenu (0);
  345. }
  346. #endif
  347.  
  348. /*****************************************************************************/
  349.  
  350. #ifdef __HAS_UI__
  351. void HandleUpdate (EventRecord *theEvent)
  352. {
  353.     DisplayString (gLastStr);
  354. }
  355. #endif
  356.  
  357. /*****************************************************************************/
  358.  
  359. #ifdef __HAS_UI__
  360. void HandleMenuSelect (long menuChoice)
  361. {
  362.     short     itemNum;
  363.     Str255    daName;
  364.     GrafPtr    ourPort;
  365.     
  366.     itemNum = LoWord(menuChoice);
  367.     switch (HiWord(menuChoice)) {
  368.         case kAppleMenu :
  369.             GetItem (gMenuHandles[kAppleMenu-1], itemNum, daName);
  370.             GetPort (&ourPort);
  371.             OpenDeskAcc (daName);
  372.             SetPort (ourPort);
  373.             break;
  374.         case kFileMenu :
  375.             // all we've got is quit
  376.             gFinished = true;
  377.             break;                
  378.         default :
  379.             break;
  380.     }
  381. }
  382. #endif
  383.  
  384. /*****************************************************************************/
  385.         
  386. void CleanupStuff ()
  387. {
  388.     CleanupSpeechRecognitionStuff ();
  389.     
  390. #ifdef __HAS_UI__
  391.     if (gDialog)
  392.         DisposeDialog (gDialog);
  393. #endif
  394. }
  395.  
  396. /*****************************************************************************/
  397.  
  398. void CleanupSpeechRecognitionStuff ()
  399. {
  400.     OSErr    status;
  401.     
  402.     if (gTopLM)
  403.         status = SRReleaseObject (gTopLM);
  404.     if (gSIModel)
  405.         status = SRReleaseObject (gSIModel);
  406.     if (gRecognizer) {
  407.         status = SRStopListening (gRecognizer);            /* stop processing incoming sound */
  408.         status = SRReleaseObject (gRecognizer);            /* balance SRNewRecognizer call */
  409.     }
  410.     if (gSystem)
  411.         status = SRCloseRecognitionSystem (gSystem);    /* balance SROpenRecognitionSystem call */
  412. }
  413.  
  414. /*****************************************************************************/
  415.  
  416. OSErr MakeALanguageModel (SRLanguageModel *model)
  417. {
  418.     const char        *lmName = "<Sample LM>";
  419.     long            refCon = kTopLMRefCon;
  420.     Str255            str;
  421.     OSErr            status;
  422.     SRLanguageModel    newModel;
  423.     
  424.     
  425.         /*    make a simple language model (LM) */
  426.     status = SRNewLanguageModel (gSystem, &newModel, lmName, strlen (lmName));
  427.     
  428.         /*    set its refcon */
  429.     if (!status)
  430.         status = SRSetProperty (newModel, kSRRefCon, &refCon, sizeof(refCon));
  431.         
  432.         /*    add some items to the top level LM */
  433.     if (!status) {
  434.         GetIndString(str, kSimpleStrsID, kQuitStr);
  435.         status = SRAddText (newModel, str+1, str[0], kQuitSpeakableItems);
  436.         GetIndString(str, kSimpleStrsID, kWhatTimeIsItStr);
  437.         status = SRAddText (newModel, str+1, str[0], kWhatTimeIsIt);
  438.         GetIndString(str, kSimpleStrsID, kWhatDayIsItStr);
  439.         status = SRAddText (newModel, str+1, str[0], kWhatDayIsIt);
  440.     }
  441.     
  442.         /*    return new LM */
  443.     if (!status)
  444.         *model = newModel;
  445.  
  446.     return status;
  447. }
  448.  
  449. /*****************************************************************************/
  450. /*****************************************************************************/
  451.  
  452. pascal OSErr DummyAEHandler (AppleEvent *theAEevt, AppleEvent* reply, long refcon)
  453. {
  454.     return noErr;
  455. }
  456.  
  457. /*****************************************************************************/
  458.  
  459. pascal OSErr HandleQuitAE (AppleEvent *theAEevt, AppleEvent* reply, long refcon)
  460. {
  461.     gFinished = true;
  462.     return noErr;
  463.  
  464. }
  465.  
  466. /*****************************************************************************/
  467.  
  468. #ifdef __USE_CALLBACKS__
  469. pascal void MyNotificationCallBack (SRCallBackStruct *param)
  470. {
  471.     OSErr                status = param->status;
  472.     SRRecognitionResult    recResult = 0;
  473.     
  474.         // Handle speech-done
  475.     if (param->what & kSRNotifyRecognitionDone) {
  476.         if (!status)
  477.             recResult = (SRRecognitionResult)(param->message);
  478.         ProcessResult (status, recResult);
  479.     }
  480. }
  481.  
  482. #else
  483.  
  484. /*****************************************************************************/
  485.  
  486. /* Here's an AppleEvent handler for handling the kAESpeechDone event of the
  487.     kAESpeechSuite -- i.e. the event indicating a recognition attempt was made.
  488.     The keySRSpeechStatus parameter gives the status of the recognition.  If it
  489.     is noErr, then the keySRSpeechResult parameter gives a SRRecognitionResult with the
  490.     various representations of the words the user spoke.
  491. */
  492.  
  493. pascal OSErr HandleSpeechDoneAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon)
  494. {
  495.     long                actualSize;
  496.     DescType            actualType;
  497.     OSErr                status = 0;
  498.     OSErr                recStatus = 0;
  499.     SRRecognitionResult    recResult = 0;
  500.     
  501.         /* Get status */
  502.     status = AEGetParamPtr(theAEevt,keySRSpeechStatus,typeShortInteger,
  503.                     &actualType, (Ptr)&recStatus, sizeof(status), &actualSize);
  504.  
  505.         /* Get result */
  506.     if (!status && !recStatus)
  507.         status = AEGetParamPtr(theAEevt,keySRSpeechResult,typeSRSpeechResult,
  508.                     &actualType, (Ptr)&recResult, sizeof(SRRecognitionResult), &actualSize);
  509.                     
  510.         /* Process result */
  511.     if (!status)
  512.         status = recStatus;
  513.     ProcessResult (status, recResult);
  514.  
  515.     return status;
  516. }
  517.  
  518. /*****************************************************************************/
  519.  
  520. /* AppleEvent handler for kAESpeechDetected event of kAESpeechSuite -- the
  521.     event indicating that recognition of an utterance is ready to begin.  We
  522.     are sent this event because we requested kSRNotifyRecognitionBeginning notification
  523.     as well as kSRNotifyRecognitionDone notification.  (See InitAndStartSpeechRecognition
  524.     routine above, where we set the kSRNotificationParam property of our SRRecognizer.)
  525. */
  526.  
  527. pascal OSErr HandleSpeechBeginningAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon)
  528. {
  529.     long                actualSize;
  530.     DescType            actualType;
  531.     OSErr                status = 0, recStatus = 0;
  532.     SRRecognizer            rec;
  533.  
  534.         /* Get status */
  535.     status = AEGetParamPtr(theAEevt,keySRSpeechStatus,typeShortInteger,
  536.                     &actualType, (Ptr)&recStatus, sizeof(status), &actualSize);
  537.                     
  538.         /* Get SRRecognizer */
  539.     if (!status && !recStatus)
  540.         status = AEGetParamPtr(theAEevt,keySRRecognizer,typeSRRecognizer,
  541.                     &actualType, (Ptr)&rec, sizeof(SRRecognizer), &actualSize);
  542.                     
  543.         /* Tell SRRecognizer to proceed with recognition attempt */
  544.     if (!status && !recStatus && rec)
  545.         SRContinueRecognition (rec);
  546. }
  547.  
  548. #endif /* __USE_CALLBACKS__ */
  549.  
  550. /*****************************************************************************/
  551.  
  552. void ProcessResult (OSErr origStatus, SRRecognitionResult recResult)
  553. {
  554.     OSErr                status = origStatus;
  555.     Str255                str;
  556.     Size                len;
  557.     SRLanguageModel        resultLM, subLM;
  558.     unsigned long        refCon;
  559.  
  560.     if (!status && recResult) {
  561.         len = sizeof(resultLM);
  562.         status = SRGetProperty (recResult, kSRLanguageModelFormat, &resultLM, &len);
  563.         if (!status) {
  564.             len = sizeof(refCon);
  565.             status = SRGetProperty (resultLM, kSRRefCon, &refCon, &len);
  566.             //    if it's a valid result form our top-level LM,
  567.             //    then parse and process its elements
  568.             if (!status && refCon == kTopLMRefCon) {
  569.                 //    TopLM should have one sub element
  570.                 status = SRGetIndexedItem (resultLM, &subLM, 0);
  571.                 if (!status) {
  572.                     len = sizeof(refCon);
  573.                     status = SRGetProperty (subLM, kSRRefCon, &refCon, &len);
  574.                     if (!status) {
  575.                         //    if subLM is from speakable items unit,
  576.                         //    pass it on to that unit to handle it
  577.                         if (refCon == kSIModelRefCon)
  578.                             SIProcessResult (subLM);
  579.                             
  580.                         //    else if it's our "quit speakable items" item, quit
  581.                         //    (alternatively, we could another routine to parse
  582.                         //    subLM, just like we call SIProcessResult above, to
  583.                         //    handle the quit sub-item and any other sub-items)
  584.                         else if (refCon == kQuitSpeakableItems) {
  585.                             gFinished = true;
  586. #ifdef __HAS_UI__
  587.                             DisplayString ("\pGoodbye.");
  588. #endif
  589.                             SpeakString ("\pGoodbye.");
  590.                         }
  591.                         
  592.                         else if (refCon == kWhatTimeIsIt)
  593.                             SayDateOrTime (false);
  594.                             
  595.                         else if (refCon == kWhatDayIsIt)
  596.                             SayDateOrTime (true);
  597.                     }
  598.                     
  599.                     //    release subelement when done with it
  600.                     SRReleaseObject (subLM);
  601.                 }
  602.             }
  603.             
  604.             //    release resultLM fetched above when done with it
  605.             SRReleaseObject (resultLM);
  606.         }
  607.     }
  608.     
  609. #ifdef __HAS_UI__
  610.     //    display error conditions
  611.     if (status == kSRRecognitionDone)
  612.         // no problem.  recognizer just didn't recognize
  613.         // one of the phrases for which we were listening.
  614.         DisplayString ("\p...");
  615.         
  616.     else if (status == kSROutOfMemory)
  617.         // ouch! we don't have enough free (system heap) memory to process 
  618.         // the utterence. speech recognition will not work until more memory 
  619.         // is available. it might make sense to set gFinished to true to quit, 
  620.         // since we can't do anything (or at least notify the user what to do)
  621.         DisplayString ("\pOut of system memory.");
  622.     else if (status)
  623.         DisplayString ("\pRecognition error");
  624. #endif
  625.  
  626.                 
  627.             // Release SRRecognitionResult since we are done with it!!! 
  628.             //    The toolbox has given us a reference to this object, and
  629.             //    assumes we are still using it until we call SRReleaseObject
  630.             //    with it.
  631.     if (!origStatus) SRReleaseObject (recResult);
  632.  
  633. }
  634.  
  635. /*****************************************************************************/
  636.  
  637. void SayDateOrTime (Boolean date)
  638. {
  639.     unsigned long     secs;
  640.     Str255            str;
  641.     
  642.     GetDateTime(&secs);
  643.     if (!date)
  644.         IUTimeString(secs, false, str);
  645.     else
  646.         IUDateString(secs, longDate, str);
  647.         
  648. #ifdef __HAS_UI__
  649.     //    Display string
  650.     DisplayString (str);
  651. #endif
  652.     
  653.     // Call text-to-speech routine to have speech synthesizer speak string
  654.     SpeakString (str);
  655. }
  656.  
  657. /*****************************************************************************/
  658. #ifdef __HAS_UI__
  659. void DisplayString (Str255 str)
  660. {
  661.     GrafPtr    oldPort;
  662.     Rect    theRect;
  663.     
  664.     memcpy (gLastStr, str, str[0]+1);
  665.     GetPort (&oldPort);
  666.     SetPort (gDialog);
  667.     theRect = ((GrafPtr)gDialog)->portRect;
  668.     theRect.bottom = theRect.bottom-30;
  669.     EraseRect(&theRect);
  670.     TextSize (12);
  671.     MoveTo (40,30);
  672.     DrawString (str);
  673.     SetPort (oldPort);
  674. }
  675. #endif
  676.  
  677. /*****************************************************************************/
  678.